import { extend } from 'umi-request';
import co from 'co';
import UUID from 'node-uuid';
import { noHeaderUrl, getCodeUrl, refreshTokenUrl, loginUrl, clientId, clientPwd } from './settings';
import { b64EncodeUnicode } from './base64';
import { setData, getData } from './localData';
import router from 'umi/router';

//token是否失效
let tokenIsLoading = false
//请求集合
let requestMap = new Map()

export const formRequest = extend({
    errorHandler:()=>{
        //登陆或刷新token错误==跳转登录页 刷新时候认证失效会出现跨域（原因：未重写oauth的刷新token方法）
        console.log("========---_____")
    }, // 默认错误处理
    //credentials: 'include', // 默认请求是否带上cookie
    requestType: 'form',
});

export const logoutRequest = extend({
    errorHandler:()=>{
        //登陆或刷新token错误==跳转登录页 刷新时候认证失效会出现跨域（原因：未重写oauth的刷新token方法）
        console.log("========---_____")
    }, // 默认错误处理
    //credentials: 'include', // 默认请求是否带上cookie
    requestType: 'json',
    headers:{
        'Authorization': 'Bearer ' + getData("token"),
        'AuthorizationRefresh': 'Bearer ' + getData("refreshToken")
    }
});

function getRequest(){
    /**
     * 配置request请求时的默认参数
     */
    const request = extend({
        errorHandler:()=>{
            //正常请求错误==跳转错误页
            console.log(123456789)
        }, // 默认错误处理
        //credentials: 'include', // 默认请求是否带上cookie
        requestType: 'json',
        // headers:{
        //     'Content-Type':'application/json;charset=UTF-8'
        // }
    });
    
    // request拦截器, 改变url 或 options.
    request.interceptors.request.use((url,options) => {
        console.log("interceptors===============================================")
        console.log(url,options)
        let id 
        let {headers} = options
        //判断是否header中加入token
        if(noHeaderUrl.indexOf(url) > -1){
            //登陆或者刷新token的接口header中加入client信息
            if(url===loginUrl||url===refreshTokenUrl){
                let auth = clientId + ":" + clientPwd
                let ss = b64EncodeUnicode(auth)
                console.log(ss)
                headers.Authorization = 'Basic ' + b64EncodeUnicode(auth)
            }
        }else{
            headers.Authorization = 'Bearer ' + getData("token")
            if(options.type){
                id = UUID.v4().replace(/-/g, "")
                // console.log("请求前生成唯一值：",id)
                let requestData = {
                    type: options.type, 
                    params: options.data
                }
                //请求存入请求集合
                requestMap.set(id,requestData)
            }
        }
        return (
            {
            url: `${url}`,
            options: { ...options, uuid: id },
            }
        );
    });
    
    // response拦截器, 处理response
    request.interceptors.response.use((response, options) => {
        function *foo(response, options){
            //克隆ReadableStream 
            let res = response.clone()
            //获取Promise 
            let promise  = res.json()
            //获取请求结果
            let resp = yield promise
            console.log("结果",resp)
            let id = options.uuid
            // console.log("响应返回唯一值：",id)
            if(!id){
                //id为undefined为没有token的请求
                return
            }
            //token过期，重新获取
            if(resp.code === 'UNAUTHORIZED' && resp.subCode === '401'){
                let req = requestMap.get(id)
                console.log("token失效获取：",req)
                if(!tokenIsLoading){
                    tokenIsLoading = true
                    refreshToken()
                }
            }else{
                // console.log("删除请求：",id)
                requestMap.delete(id)
            }
        }
        co(foo(response,options))
        return response;
    });

    return request;
}


//获取code
function getCode(){
    const request = extend({requestType: 'form'});
    return request(getCodeUrl,{ method:'post', data:{}})
}

//刷新token
async function refreshToken(){
    // const request = extend({
    //     errorHandler, // 错误处理
    //     //credentials: 'include', // 默认请求是否带上cookie
    //     requestType: 'form',
    // });
    let res = await formRequest(refreshTokenUrl, { method:'post', data: {refresh_token: getData('refreshToken'), grant_type:"refresh_token"} })
    console.log("刷新token结果",res)
    if(res){
        tokenIsLoading = false
        if(res.access_token){
            //重置token
            setData("token",res.access_token)
            //重置权限
            reAuthorized()
            // console.log("请求集合",requestMap)
            //请求重发
            requestRedo()
        }else{
            //返回登陆页面
            router.push("/login")
        }
    }else{
        //返回登陆页面
        router.push("/login")
    }
}

//重置权限
function reAuthorized(){
    window.g_app._store.dispatch({
        type: "user/fetchTokenInfo",
        payload: {}
    })
}

//请求重发
function requestRedo(){
    console.log("开始重发")
    let keySet = []
    requestMap.forEach(function (value, key, map){
        keySet.push(key)
    })
    keySet.forEach((key)=>{
        // console.log("开始重新发送：",key)
        let req = requestMap.get(key)
        //重发后删除这个请求
        requestMap.delete(key)
        // console.log("重发后删除这个请求====>",key,req);
        //如果type（action有效） 使用全局_store来dispatch
        if(req.type){
            window.g_app._store.dispatch({
                type: req.type,
                payload: req.params
            })
        }
    })
}

//请求前申请接口code
function getProxy(){
    let proxy = new Proxy(getRequest(),{
        //拦截get操作
        get (target, key, receiver) {
            // console.log("被读取")
            // console.log(key)
            if (['request', 'get', 'delete', 'head', 'post', 'put', 'patch'].includes(ket)) {
                return new Proxy(Reflect.get(),{
                    apply: this.apply
                })
            }else{
                return Reflect.get(target, key, receiver)
            }
        },
        //拦截call和apply操作
        apply (target, cxt, args) {
            return new Promise((resolve, reject) => {
                let url = args[0]
                // console.log("apply===========================>",url,args)
                // function *foo(target,args){
                //     let resp = yield getCode()
                //     if(resp.success){
                //         args[0] = args[0] + '?code=' + resp.data.code
                //         //装载自定义参数到options
                //     }
                // }
                // co(foo(target,args))
                args[1].type = args[2]
                target(...args).then(res => resolve(res)).catch(error => reject(error))
            })
        }
    })

    return proxy
}

export default getProxy()